#ifndef __MAX30102__H__
#define __MAX30102__H__
#include "BasicInterface.h"
//*** <<< Use Configuration Wizard in Context Menu >>> ***
//STATUS
#define INTERRUPT_STATUS_1 0x00//中断标志位1
#define INTERRUPT_STATUS_2 0x01//中断标志位2
#define INTERRUPT_ENABLE_1 0x02//中断使能1
#define INTERRUPT_ENABLE_2 0x03//中断使能2
//FIFO
#define FIFO_WRITE_POINTER 0x04
#define FIFO_OVERFLOW_COUNTER 0x05
#define FIFO_READ_POINTER 0x06
#define FIFO_DATA 0x07
//CONFIGURATION
#define FIFO_CONFIGURATION 0x08
#define MODE_CONFIGURATION 0x09
#define SPO2_CONFIGURATION 0x0A
#define LED1_AMPLITUDE_CONFIGURATION 0x0C
#define LED2_AMPLITUDE_CONFIGURATION 0x0D
#define PROXIMITY_MODE_LED_PULSE_AMPLITUDE 0x10
#define MULTI_LED_MODE_CONTROL_REGISTERS1 0x11
#define MULTI_LED_MODE_CONTROL_REGISTERS2 0x12
//DIE TEMPERATURE
#define DIE_TEMP_INTEGER 0x1F
#define DIE_TEMP_FRACTION 0x20
#define DIE_TEMPERATURE_CONFIG 0x21
//PROXIMITY FUNCTION
#define PROXIMITY_INTERRUPT_THRESHOLD 0x30
//PART ID
#define REVISION_ID 0xFE
#define PART_ID 0xFF

class MAX30102
{
private:
	const BasicIO& Port;
	const BasicDebug& Debug;
	uint32_t Address;
	bool AdjustScale();
protected:

public:
	//INTERRUPT FLAGS
	typedef enum
	{
		IT_FIFO_Almost_Full = 0x80,
		IT_New_FIFO_Data_Ready = 0x40,
		IT_Ambient_Light_Cancellation_Overflow = 0x20,
		IT_Proximity_Threshold_Triggered = 0x10,
		IT_Power_Ready = 0x02,
		IT_Internal_Temperature_Ready = 0x01
	} Interrupt_t;

	typedef enum
	{
		Average_1,
		Average_2,
		Average_4,
		Average_8,
		Average_16,
		Average_32
	} Average_t;

	typedef enum
	{
		Mode_HeartRate = 0x02,
		Mode_SpO2 = 0x03,
		Mode_MultiLED = 0x07
	} Mode_t;

	typedef enum
	{
		Scale_2048,
		Scale_4096,
		Scale_8192,
		Scale_16384
	} Scale_t;

	typedef enum
	{
		SampleRate_50HZ,
		SampleRate_100HZ,
		SampleRate_200HZ,
		SampleRate_400HZ,
		SampleRate_800HZ,
		SampleRate_1000HZ,
		SampleRate_1600HZ,
		SampleRate_3200HZ
	} SampleRate_t;

	typedef enum
	{
		Width_15Bits,
		Width_16Bits,
		Width_17Bits,
		Width_18Bits,
	} Width_t;

	typedef enum
	{
		Led_None,
		Led_RED,
		Led_IR,
		Led_RED_PILOT = 0x05,
		Led_IR_PILOT = 0x06
	} Led_t;

	MAX30102(uint8_t a, const BasicIO& p, const BasicDebug& d) : Port(p), Debug(d), Address(a << 25) {};

	Interrupt_t GetInterruptFlag(uint8_t Num)
	{
		uint8_t buf;
		Port.Read(Address | INTERRUPT_STATUS_1 + Num, &buf, 1);
		return (Interrupt_t)buf;
	}

	bool GetInterruptStatus(uint8_t);

	void SetInterrupt(Interrupt_t, bool);

	void SetFIFOWritePos(uint8_t Pos)
	{
		Port.Write(Address | FIFO_WRITE_POINTER, &Pos, 1);
	}

	uint8_t GetFIFOWritePos()
	{
		uint8_t ret;
		Port.Read(Address | FIFO_WRITE_POINTER, &ret, 1);
		return ret;
	}

	void SetFIFOOverFlow(uint8_t OverFlow)
	{
		Port.Write(Address | FIFO_OVERFLOW_COUNTER, &OverFlow, 1);
	}

	uint8_t GetFIFOOverFlow()
	{
		uint8_t ret;
		Port.Read(Address | FIFO_OVERFLOW_COUNTER, &ret, 1);
		return ret;
	}

	void SetFIFOReadPos(uint8_t Pos)
	{
		Port.Write(Address | FIFO_READ_POINTER, &Pos, 1);
	}

	uint8_t GetFIFOReadPos()
	{
		uint8_t ret;
		Port.Read(Address | FIFO_READ_POINTER, &ret, 1);
		return ret;
	}

	void GetFIFOData1(void* Ptr, uint8_t Len)
	{
		for (uint8_t i = 0; i < Len; i++)
			Port.Read(Address | FIFO_DATA, static_cast<uint8_t*>(Ptr) + i, 1);
	}

	void GetFIFOData(void* Ptr, uint8_t Len)
	{
		Port.Read(Address | FIFO_DATA, Ptr, Len);
	}

	void SetSampleAveraging(Average_t);

	void SetFIFORolls(bool);

	void SetFIFOAlmostFullValue(uint8_t);

	BasicIO::Resault SetShutDown(bool);

	BasicIO::Resault Reset()
	{
		uint8_t buf = 0x40;
		return Port.Write(Address | MODE_CONFIGURATION, &buf, 1);
	}

	BasicIO::Resault SetMode(Mode_t);

	void SetSpO2FullScale(Scale_t);

	void SetSampleRate(SampleRate_t);

	void SetDataWidth(Width_t);

	void SetLEDAmplitude(uint8_t Num, uint8_t Amplitude)
	{
		Port.Write(Address | LED1_AMPLITUDE_CONFIGURATION + Num - 1, &Amplitude, 1);
	}

	void SetProximityModeLEDAmplitude(uint8_t Amplitude)
	{
		Port.Write(Address | PROXIMITY_MODE_LED_PULSE_AMPLITUDE, &Amplitude, 1);
	}

	void SetConversionList(const Led_t(&list)[4]);//用于Multi-LED模式

	float GetTemperature();

	void StartTemperatureMeasure()
	{
		uint8_t buf = 0x01;
		Port.Write(Address | DIE_TEMPERATURE_CONFIG, &buf, 1);
	}

	void SetProximityInterruptThreshold(uint8_t Threshold)
	{
		Port.Write(Address | PROXIMITY_INTERRUPT_THRESHOLD, &Threshold, 1);
	}

	void DeInit();

	bool AutoScale();

	uint8_t GetRevID();

	uint8_t GetPartID();

	void RegDump();
};
//<h>Interrupt Setting
//<i>Enable/Disable Specific Interrupt Source
//<q.7>FIFO Almost Full
//<q.6>New FIFO Data Ready
//<q.5>Ambient Light Cancellation OverFlow
//<q.4>Proximity Threshold Triggered

//<q1.1>Internal Temperature Ready
//</h>

//<h>Configurations
//<i>Configure The Chip
//<o2.5..7>Sample Averaging <0=>1(No Averaging) <1=>2
//                          <2=>4               <3=>8
//                          <4=>16              <5=>32
//<i>Use How Many Numbers To Calculate Average Number
//<q2.4>FIFO Rolls on Full
//<i>If enable,The new data will cover old data when FIFO is full
//<o2.0..3>FIFO Almost Full Value <0x0-0xF>
//<i>Define how many the FIFO remains will trigger the interrupt

//<q3.7>Shutdown
//<i>Make chip Shutdown at PowerOn
//<o3.0..2>Mode <2=>Heart Rate(Red only) <3=>SpO2(Red and IR) <7=>Multi-LED(Red and IR)
//<i>Select initial mode

//<o4.5..6>SpO 2 ADC Range Control(Full Scale)
//<0=>2048 <1=>4096 <2=>8192 <3=>16384
//<i>Set maxmum value
//<o4.2..4>SpO2 Sample Rate
//<0=>50HZ <1=>100HZ <2=>200HZ <3=>400HZ <4=>800HZ <5=>1000HZ <6=>1600HZ <7=>3200HZ
//<i>Set initial sample rate
//<o4.0..1>LED Pulse Width Control and ADC Resolution
//<0=>15Bit <1=>16Bit <2=>17Bit <3=>18Bit
//<i>ADC Bits

//<o5>LED1 Pulse Amplitude<0x00-0xFF>
//<o6>LED2 Pulse Amplitude<0x00-0xFF>
//<o7>Proximity Mode LED Pulse Amplitude<0x00-0xFF>

//<h>Conversion List
//<i>ONLY Multi-LED Mode can use this
//<o8.0..2>First Conversion
//<0=>Led_None <1=>Led_Red <2=>Led_IR <5=>Led_RED_PILOT <6=>Led_IR_PILOT
//<o8.4..6>Second Conversion
//<0=>Led_None <1=>Led_Red <2=>Led_IR <5=>Led_RED_PILOT <6=>Led_IR_PILOT
//<o9.0..2>Third Conversion
//<0=>Led_None <1=>Led_Red <2=>Led_IR <5=>Led_RED_PILOT <6=>Led_IR_PILOT
//<o9.4..6>Fourth Conversion
//<0=>Led_None <1=>Led_Red <2=>Led_IR <5=>Led_RED_PILOT <6=>Led_IR_PILOT
//</h>
//</h>

//<h>Proximity
//<o10>Proximity Mode Interrupt Threshold<0x00-0xFF>
//<i>Proximity interrupt trigger threshold
//</h>
#define INTERRUPT_ENABLE_1_VALUE 0x40
#define INTERRUPT_ENABLE_2_VALUE 0x00
#define FIFO_CONFIGURATION_VALUE 0x02
#define MODE_CONFIGURATION_VALUE 0x83
#define SPO2_CONFIGURATION_VALUE 0x67

#define LED1_AMPLITUDE_CONFIGURATION_VALUE 0x40
#define LED2_AMPLITUDE_CONFIGURATION_VALUE 0x40
#define PROXIMITY_MODE_LED_PULSE_AMPLITUDE_VALUE 0x40
#define MULTI_LED_MODE_CONTROL_REGISTERS1_VALUE 0x21
#define MULTI_LED_MODE_CONTROL_REGISTERS2_VALUE 0x00

#define PROXIMITY_INTERRUPT_THRESHOLD_VALUE 0x70


//*** <<< end of configuration section >>>    ***
#endif
